#include<iostream>
#include<signal.h>
#include<cstring>
  #include <sys/types.h>
       #include <sys/wait.h>
#include<ctime>
 #include <unistd.h>
using namespace std;


//问题 :在pending位图中，信号是执行信号捕捉方法之前把1变为0  ，还是执行信号捕捉方法之后把1变为0？
// 执行信号捕捉方法之前，从1变为0，再调用捕捉方法


// extern  void  PrintPending()  ;

// //捕捉方法
// void handler(int signo)
// {
//     PrintPending()  ;
//     cout << "catch a signal: " << signo << endl;
 
// } 

// void    PrintPending()  //打印pending表
// {
// sigset_t set;
// sigpending (&set) ;//读取进程的pending表
//   for (int signo = 1; signo <= 31; signo++)
//   {
//     if(sigismember(&set ,signo) ==1 )
    
//         cout << "1";
     
//         else
//              cout << "0";
//   }
//  cout << "\n";

// }



// int main ()
// {

//     struct sigaction act , oldact ;
//     memset(&act ,0 ,sizeof(act));
//     memset(&oldact ,0 ,sizeof(oldact));
//     sigemptyset(&act.sa_mask)  ;//使其中所有信号的对应bit清零
     
//      //讲信号的默认处理动作修改未自定义动作
//      act.sa_handler =handler;  //handler是函数指针
//     sigaction(2,&act, &oldact);//对2号信号捕捉


//  while (true)
//     {
//         cout << "I am a process: " << getpid() << endl;
//         sleep(1);
//     }

//     return 0 ;
// }






// //当某个信号的处理函数被调用时,内核自动将当前信号加入进程的信号屏蔽字,当信号处理函数返回时自动恢复原来的信号屏蔽字
// extern  void  PrintPending()  ;
 
// //捕捉方法
// void handler(int signo)
// {
//     cout << "catch a signal, signal number : " << signo << endl;
//     while (true)
//     {
//         PrintPending();
//         sleep(1);
//     }
// }

// void    PrintPending()  //打印pending表
// {
// sigset_t set;
// sigpending (&set) ;//读取进程的pending表
//   for (int signo = 1; signo <= 31; signo++)
//   {
//     if(sigismember(&set ,signo) ==1 )
    
//         cout << "1";
     
//         else
//              cout << "0";
//   }
//  cout << "\n";

// }



// int main ()
// {

//     struct sigaction act , oldact ;
//     memset(&act ,0 ,sizeof(act));
//     memset(&oldact ,0 ,sizeof(oldact));
//     sigemptyset(&act.sa_mask)  ;//使其中所有信号的对应bit清零
     
//      //讲信号的默认处理动作修改未自定义动作
//      act.sa_handler =handler;  //handler是函数指针
//     sigaction(2,&act, &oldact);//对2号信号捕捉


//  while (true)
//     {
//         cout << "I am a process: " << getpid() << endl;
//         sleep(1);
//     }

//     return 0 ;
// }




//当某个信号的处理函数被调用时,内核自动将当前信号加入进程的信号屏蔽字,当信号处理函数返回时自动恢复原来的信号屏蔽字
//信号被处理的时候，对应的信号也会被添加到block表中，防止信号捕捉被嵌套调用
// extern  void  PrintPending()  ;
 
// //捕捉方法
// void handler(int signo)
// {
//     cout << "catch a signal, signal number : " << signo << endl;
//     while (true)
//     {
//         PrintPending();
//         sleep(1);
//     }
// }

// void    PrintPending()  //打印pending表
// {
// sigset_t set;
// sigpending (&set) ;//读取进程的pending表
//   for (int signo = 1; signo <= 31; signo++)
//   {
//     if(sigismember(&set ,signo) ==1 )
    
//         cout << "1";
     
//         else
//              cout << "0";
//   }
//  cout << "\n";

// }



// int main ()
// {

//     struct sigaction act , oldact ;
//     memset(&act ,0 ,sizeof(act));
//     memset(&oldact ,0 ,sizeof(oldact));
//     sigemptyset(&act.sa_mask)  ;//使其中所有信号的对应bit清零
//  sigaddset(&act.sa_mask, 1);  //屏蔽1号信号
//     sigaddset(&act.sa_mask, 3);//屏蔽3号信号
//     sigaddset(&act.sa_mask, 4);//屏蔽4号信号 

//      //信号的默认处理动作修改为自定义动作
//      act.sa_handler =handler;  //handler是函数指针
//     sigaction(2,&act, &oldact);//对2号信号捕捉


//  while (true)
//     {
//         cout << "I am a process: " << getpid() << endl;
//         sleep(1);
//     }

//     return 0 ;
// }
//   volatile int flag = 0;  //因为优化，导致我们内存不可见了volatile关键字:防止编译器过度优化，保持内存的可见性
//  void handler(int signo)
// {
// cout << "catch a signal: " << signo << endl;
//      flag = 1;
// }

    

// int main()
// {
//     signal(2, handler);
//     // 在优化条件下， flag变量可能被直接优化到CPU内的寄存器中
//     while(!flag); // flag 0, !falg 真

//     cout << "process quit normal" << endl;
//     return 0;
// }





// void handler(int signo)
// {   

  
//   //子进程在进行等待时，采用基于信号的方式进行等待,子进程等待写入到信号捕捉函数中
//      sleep(5);
// pid_t rid=waitpid(-1, nullptr, 0);//-1表示等待任意一个子进程

// cout << "I am proccess: " << getpid() << " catch a signo: " << signo << "child process quit: " << rid << endl;

// }

// int main()
// {
//     signal(17 ,handler);
//     pid_t id = fork();
//         if (id == 0)  //child
//         {
//             while (true)
//             {
//                 cout << "I am child process: " << getpid() << ", ppid: " << getppid() << endl;
//                 sleep(5);
//                 break;
//             }
//             cout << "child quit!!!" << endl;
//             exit(0);    
//         }

//          // father
//     while (true)
//     {
//         cout << "I am father process: " << getpid() << endl;
//         sleep(1);
//     }
//     return 0 ;
// }



// void handler(int signo)
// {   

  
//   //子进程在进行等待时，采用基于信号的方式进行等待,子进程等待写入到信号捕捉函数中
//      sleep(5);
// pid_t rid=waitpid(-1, nullptr, 0);//-1表示等待任意一个子进程

// cout << "I am proccess: " << getpid() << " catch a signo: " << signo << "child process quit: " << rid << endl;

// }

// int main()
// {
//        signal(17 ,handler);
//          //多个进程
//     for ( int i = 0 ; i <10 ; i++)
//     {
         
//         pid_t id = fork();  
//         if (id == 0)  //child
//         {
//             while (true)
//             {
//                 cout << "I am child process: " << getpid() << ", ppid: " << getppid() << endl;
//                 sleep(5);
//                 break;
//             }
//             cout << "child quit!!!" << endl;
//             exit(0);    
//         }
      
//          sleep(1);

         
//     }
   
//       // father
//             while (true)
//             {
//                 cout << "I am father process: " << getpid() << endl;
//                 sleep(1);
//             }
     

//     return 0 ;
// }



void handler(int signo)
{   

  
  //子进程在进行等待时，采用基于信号的方式进行等待,子进程等待写入到信号捕捉函数中
     sleep(5);
     pid_t rid ; 
     //以非阻塞方式等待进程退出
  while ( (rid = waitpid(-1, nullptr, 0)) > 0)    //-1表示等待任意一个子进程
  {
     //回收进程成功
      cout << "I am proccess: " << getpid() << " catch a signo: " << signo << "child process quit: " << rid << endl;
  }

}

int main()
{
    srand(time (nullptr)); //随机数
       signal(17 ,handler);
         //多个进程
    for ( int i = 0 ; i <10 ; i++)
    {
         
        pid_t id = fork();  
        if (id == 0)  //child
        {
            while (true)
            {
                cout << "I am child process: " << getpid() << ", ppid: " << getppid() << endl;
                //sleep(5);
                sleep(rand()%10+5);  // 范围在 5 到 14 
                break;
            }
            cout << "child quit!!!" << endl;
            exit(0);    
        }
      
         //sleep(1);
    }
   
      // father
            while (true)
            {
                cout << "I am father process: " << getpid() << endl;
                sleep(1);
            }
     

    return 0 ;
}